<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // vue响应式是通过Observer创建一个监视的实例对象，用于监视data中属性的变化，我们目前只是把核心的内容简单写一下
        // 还需要完善的
        // （1）如果是多层级对象，对象套对象现在没有考虑
        // （2）没有把属性直接挂载到vm下边
        // （3）修改属性的时候，我们输出了一句话，而vue是调用方法重新解析vue模板

        let data = {
            name: "名师",
            address: "北京",
        }

        // 创建一个监视的实例对象，用于监视data中属性的变化
        const obs = new Observer(data)

        // 我们自己写的函数也能new？new之后有什么用？返回什么？里边的this是谁？
        // of Course
        //         new的过程说的比较直白，当我们new一个构造器，主要有三步：
        //                      • 创建一个空对象，将它的引用赋给 this，继承函数的原型。
        //                      • 通过 this 将属性和方法添加至这个对象
        //                      • 最后返回 this 指向的新对象，也就是实例（如果没有手动返回其他的对象）

        console.log(obs)
        // 准备一个vm对象
        let vm = {}
        vm._data = data = obs

        // 这里我有个问题？这里我们创建了一个响应式对象，返回来赋值给data和开始那个不一样嘛
        // 首先对象是在内存中创建一个地址
        //              （1）开始创建了对象==》obj1，然后赋值给data
        //              （2）new一个对象，传入的是data但是还是原来的obj1这个对象，创建了新的对象==>obj2，同时obj1和obj2变成了响应式的
        //              （3）由于new是返回对应this指向的对象，也就是obj2，所以obj2赋值给obs和data和vm._data
        //              （4）尽管我们传入是data还赋值data，但是data所表示的对象不同了，所以不是同一个对象，所以不会出现错误响应式那样内存溢出

        function Observer(obj) {
            // 汇总对象中所有属性形成一个数组
            const keys = Object.keys(data)
            // 遍历
            console.log(keys)
            keys.forEach((item) => {
                Object.defineProperty(this, item, { //从上边new过程解析，我们知道这个this指向new出来空对象，在这个里边添加响应式属性
                    // 响应式获取和修改都修改data的，然后创建出来的对象赋值给data
                    get() {
                        return obj[item]
                    },
                    set(val) {
                        console.log(`${item}被改了，我要去解析模板，生成虚拟dom，转换为真实dom渲染到页面上`)
                        obj[item] = val
                    },
                })
            })
        }
    </script>

</body>

</html>